home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- **
- ** Folder Name: BS
- ** File Name: Resident.c
- **
- ** Copyright: © 1993 by Siren Enterprises, all rights reserved.
- **
- ** Description: Resident code segment for Lil´ BeepSay
- **
- *******************************************************************************
- ** A U T H O R I D E N T I T Y
- *******************************************************************************
- **
- ** Initials Name
- ** -------- -----------------------------------------------
- ** kw Ken Wieschhoff
- **
- *******************************************************************************
- ** R E V I S I O N H I S T O R Y
- *******************************************************************************
- **
- ** Date Time Author Description
- ** -------- ----- ------ ---------------------------------------------
- ** 05/17/93 17:44 kw Original version
- **
- ******************************************************************************/
-
- #include <Traps.h>
- #include <GestaltEqu.h>
- #include <Notification.h>
- #include <PLStringFuncs.h>
- #include <Quickdraw.h>
- #include <Packages.h>
- #include <errors.h>
- #include <AppleEvents.h>
- #include "Resident.h"
- #include "Preferences.h"
- #include "Utilities.h"
-
-
- #define BTstQ(arg, bitnbr) (arg & (1 << bitnbr))
- #define kDoAsync true
-
- Str255 gFileName;
- short gFileVolume;
- long gFileDirID;
- PreferencesHdl gPrefs = nil;
-
- pascal OSErr ReadPreferences();
- pascal OSErr OurGestaltFunc( OSType selector, long *response);
- pascal void OurSysBeep(short duration);
- OSErr InstallGestalt( void);
- pascal OSErr _MAIN( StringPtr fileName, short volume, long dirID);
- pascal void ShowStr( StringPtr str);
- pascal void ShowStrNum( StringPtr str, OSErr err);
- pascal void _OurSysBeep(short duration);
- OSErr InitAppleEvents();
- pascal OSErr OurSpeakTheText(StringPtr itsText, Boolean async);
- pascal OSErr AESetBeepSayState(AppleEvent *messagein, AppleEvent *reply, long refIn);
- pascal OSErr AESpeakBeepSayPhrase(AppleEvent *messagein, AppleEvent *reply, long refIn);
-
-
- pascal OSErr MAIN( StringPtr fileName, short volume, long dirID)
- {
- Handle newA5;
- OSErr err;
- long hostA5;
-
- hostA5 = GetA5();
-
- newA5 = NewHandle( 0); // Handle for globals
- if( !newA5)
- return (memFullErr);
-
- // Make a new A5 world.
- err = MakeA5World( newA5); // Sizes the Handle
- if( err != noErr) {
- DisposeHandle( newA5);
- newA5 = nil;
- return ( err);
- }
-
- *OldA5() = (long) newA5;
- FlushInstructionCache(); // '040 Compatibility
- FlushDataCache();
-
- SetA5((long)StripAddress((*newA5)) + A5Size() - 32);
-
- // Do the work
- err = _MAIN( fileName, volume, dirID);
-
- // Restore the A5
- RestoreA5World( hostA5);
-
- return ( err);
-
- }
-
- pascal OSErr _MAIN( StringPtr fileName, short volume, long dirID)
- {
- short err = noErr;
-
-
- // Install system traps, etc.
- InitGraf( &qd.thePort);
-
- /*
- Remember supplied file info (unused so far but useful if we need to
- get resources from the cdev)
- */
- PLstrcpy( gFileName, fileName);
- gFileVolume = volume;
- gFileDirID = dirID;
-
- // Read the current preferences. File will be created if it doesn't exist.
- err = _ReadPreferences( &gPrefs, kBeepSayPrefs);
- if ( err != noErr)
- goto exit;
-
- // Install our Gestalt function.
- err = InstallGestalt();
- if ( err != noErr)
- goto exit;
-
- err = InstallTrap();
-
- if ( err != noErr)
- goto exit;
-
- // Add our Apple Event Handlers
- err = InitAppleEvents();
- exit:
-
- return( err);
- }
-
-
- TrapType GetTrapType(short theTrap)
-
- {
- // OS traps start with A0, Tool with A8 or AA.
- if ((theTrap & 0x0800) == 0) // per D.A.
- return OSTrap;
- else
- return ToolTrap;
- } // GetTrapType
-
-
-
- pascal OSErr InstallTrap( void)
- {
-
- Ptr newSysbeep = (Ptr) &OurSysBeep;
-
- (*OldSysBeep()) = NGetTrapAddress( _SysBeep, GetTrapType( _SysBeep));
- FlushInstructionCache(); // '040 Compatibility
- FlushDataCache();
- NSetTrapAddress( (long) StripAddress( newSysbeep ), _SysBeep,
- GetTrapType( _SysBeep));
- return( noErr);
- }
-
- OSErr InstallGestalt( void)
- {
- short err;
-
-
- err = NewGestalt(cKBPSAChangedResource, (ProcPtr) StripAddress((Ptr) &OurGestaltFunc));
- return( err);
- }
-
- // InitAEStuff installs the appleevent handlers
- OSErr InitAppleEvents(void)
- {
- struct AEinstalls {
- AEEventClass theClass;
- AEEventID theEvent;
- EventHandlerProcPtr theProc;
- } HandlersToInstall[] = {
- {
- kBeepSaySignature, kBeepSaySetState, AESetBeepSayState
- }, {
- kBeepSaySignature, kBeepSaySpeakPhrase, AESpeakBeepSayPhrase
- },
-
- };
- typedef struct AEinstalls AEinstalls;
-
- OSErr aevtErr = noErr;
- long aLong = 0;
- Boolean hasAppleEvents = false;
- short index;
-
-
- // Check for AppleEvents
- aevtErr = Gestalt(gestaltAppleEventsAttr, &aLong);
- if (aevtErr)
- return (aevtErr);
-
- // Install Handlers in System Heap.
- for (index = 0; index < ((sizeof(HandlersToInstall) / sizeof(AEinstalls))); index++) {
- aevtErr = AEInstallEventHandler(HandlersToInstall[index].theClass,
- HandlersToInstall[index].theEvent,
- HandlersToInstall[index].theProc, 0, true);
- if (aevtErr)
- return (aevtErr);
- }
-
- return ( noErr);
- }
-
- pascal void OurSysBeep(short duration)
- {
- long hostA5;
- Handle ourA5 = *OldA5();
-
- hostA5 = GetA5();
-
- // Set up our globals.
- SetA5((long)StripAddress((*ourA5)) + A5Size() - 32);
-
- // Call our trap
- _OurSysBeep( duration);
-
- // Restore the A5
- RestoreA5World( hostA5);
-
- }
-
- pascal void OurEndOfSpeechCallBack( SpeechChannel channel, long refCon)
- {
- # pragma unused(refCon)
-
- (void)DisposeSpeechChannel( channel);
-
- }
-
- pascal void _OurSysBeep(short duration)
- {
- OSErr err = -1;
- long result;
- long timeOut;
- short numChannels = 0;
-
- // Is it on??
- if ( !(**gPrefs).on_off) {
- CallOldSysBeep(duration);
- return;
- }
-
- // Is the speech manager available?
- err = Gestalt( gestaltSpeechAttr, &result);
- if ((err != noErr) || !(result & (1 << gestaltSpeechMgrPresent))) {
- CallOldSysBeep( duration);
- return;
- }
-
- // Wait for an available channel for 6 seconds.
- if ( (**gPrefs).onlyPlayOne) {
- timeOut = TickCount() + 360;
- while( ((numChannels = SpeechBusySystemWide()) > 0) && (TickCount() < timeOut))
- {
- } // wait for it.
-
- if ( numChannels > 0) {
- CallOldSysBeep( duration);
- return;
- }
-
- }
-
- // Lock the preferences handle
- HLock( (Handle) gPrefs);
- err = OurSpeakTheText( (**gPrefs).theText, kDoAsync);
- HUnlock( (Handle) gPrefs);
-
- if ( err != noErr) {
- CallOldSysBeep( duration);
- return;
- }
-
- return;
-
- }
-
- typedef pascal void (*ourSysBeepPtr)(short duration);
- pascal void CallOldSysBeep(duration)
- {
- ourSysBeepPtr trap;
-
- // Retrieve the old trap.
- trap = (ourSysBeepPtr) *OldSysBeep();
-
- // Call prior SysBeep
- (*trap)(duration);
-
- return;
-
- }
-
- pascal OSErr _OurGestaltFunc( OSType selector, long *response)
- {
- short err = noErr;
-
- *response = 0;
-
- switch( selector) {
-
- case cKBPSAChangedResource: // Preferences Changed
-
- *response = (long *) ReadPreferences;
- break;
-
- default:
- err = gestaltUndefSelectorErr;
- break;
-
- }
-
- exit:
-
- return( err);
- }
-
- pascal OSErr OurGestaltFunc( OSType selector, long *response)
- {
- short err;
- long hostA5;
- Handle ourA5 = *OldA5();
-
- hostA5 = GetA5();
-
-
- SetA5((long)StripAddress((*ourA5)) + A5Size() - 32);
-
- // Do the work
- err = _OurGestaltFunc( selector, response);
-
- // Restore the A5
- RestoreA5World( hostA5);
-
- return( err);
- }
-
- pascal OSErr ResetPreferences()
- {
- short err;
- Handle ourA5 = *OldA5();
- PreferencesHdl itsPrefs = nil;
-
-
- // Read the preferences from disk
- err = _ReadPreferences( &itsPrefs, kBeepSayPrefs);
-
- // If no errors set the new preferences here.
- if ( err == noErr) {
- DisposeHandle( (Handle) gPrefs);
- gPrefs = itsPrefs;
- }
-
- return( err);
- }
-
- pascal OSErr ReadPreferences()
- {
- short err;
- long hostA5;
- Handle ourA5 = *OldA5();
-
- hostA5 = GetA5();
-
-
- SetA5((long)StripAddress((*ourA5)) + A5Size() - 32);
-
- // Do the work
- err = ResetPreferences();
-
- // Restore the A5
- RestoreA5World( hostA5);
-
- return( err);
- }
-
- pascal void ShowStrNum( StringPtr str, OSErr err)
- {
- Str255 errText, strText;
-
- NumToString( (long) err, errText);
-
- PLstrcpy(strText, str);
- PLstrcat(strText,"\p Error = ");
- PLstrcat(strText, errText);
- ShowStr( strText);
- }
-
- pascal void _DisposeError( NMRec *theNMRec)
- {
- OSErr err;
-
- err = NMRemove( theNMRec);
-
- DisposePtr( (Ptr) theNMRec->nmStr );
- DisposePtr( (Ptr) theNMRec );
- }
-
- pascal void DisposeError( NMRec *theNMRec)
- {
- long hostA5;
- Handle ourA5 = *OldA5();
-
- hostA5 = GetA5();
-
-
- SetA5((long)StripAddress((*ourA5)) + A5Size() - 32);
-
- _DisposeError( theNMRec);
-
- RestoreA5World( hostA5);
- }
-
- pascal void ShowStr( StringPtr str)
- {
- NMRec* nmPtr;
- StringPtr text;
-
- // Call the Notification Manager to display errors.
- nmPtr = (NMRec*) NewPtr( sizeof( NMRec) );
- if ( nmPtr == nil) {
- return;
- }
- text = (StringPtr) NewPtr( str[0] + 1);
- if ( text == nil) {
- DisposePtr( (Ptr) nmPtr);
- return;
- }
- PLstrcpy( text, str);
-
- nmPtr->qType = 8;
- nmPtr->nmMark = 0; // no mark in application menu
- nmPtr->nmIcon = nil; // nil = no icon in menubar or a handle to SICN resource
- nmPtr->nmSound = (Handle)-1; // pick a sound, use -1 for System Beep or nil for no sound.
- nmPtr->nmStr = text; // display this string in dialog
- nmPtr->nmResp = (NMProcPtr)DisposeError; // Routine to dispose of the pointer block. (nil - Use default)
- nmPtr->nmRefCon = 0L; // no refcon
-
- if( NMInstall( nmPtr) != noErr) {
- DisposePtr( (Ptr) nmPtr);
- DisposePtr( (Ptr) text);
- }
- }
-
- pascal OSErr OurSpeakTheText(StringPtr itsText, Boolean async)
- {
- OSErr err = -1;
- long timeOut = TickCount() + 180;
- SpeechChannel theChannel;
- long hostA5;
-
- hostA5 = GetA5();
-
- // Try for no more than 3 seconds to get a new speech channel.
- while (( err != noErr) && (TickCount() < timeOut))
- err = NewSpeechChannel( &(**gPrefs).theVoice, &theChannel);
-
- if ( err != noErr)
- return (err);
-
- // Set the speech rate and pitch.
- (void)SetSpeechPitch( theChannel, (**gPrefs).thePitch);
- (void)SetSpeechRate( theChannel, (**gPrefs).theRate);
-
- // Set our A5 world to use when using callbacks.
- err = SetSpeechInfo( theChannel, soCurrentA5, &hostA5);
-
- if ( err != noErr)
- return (err);
-
- // Set a callback to use to dispose the speech channel.
- if ( async) {
- err = SetSpeechInfo( theChannel, soSpeechDoneCallBack, &OurEndOfSpeechCallBack);
-
- if ( err != noErr)
- return (err);
- }
-
- // Speak the text.
- err = SpeakText( theChannel, &itsText[1], itsText[0]);
-
- if ( async)
- return (err);
-
- while( SpeechBusy() > 0)
- {} // Wait for the speech to complete.
-
-
- return ( DisposeSpeechChannel( theChannel));
-
-
- }
-
-
- void AddToReply(AppleEvent *reply, Str255 theWords, long theError)
- {
- OSErr err = noErr;
- long errNo;
- DescType returnedType;
- Size returnedSize;
-
- // First, is there a reply hanging out?
- if (reply) {
- // test to see if there is one already
- err = AEGetParamPtr(reply, keyErrorNumber, typeLongInteger, &returnedType, (Ptr)&errNo, sizeof(long),
- &returnedSize);
-
- if (err == errAEDescNotFound) {
- // cool, press on.
- err = AEPutParamPtr(reply, keyErrorNumber, typeLongInteger, (Ptr)&theError, sizeof(long));
- if (!err)
- err = AEPutParamPtr(reply, keyErrorString, typeChar, (Ptr)&theWords[1], theWords[0]);
-
- }
- }
- }
-
- pascal OSErr _AESetBeepSayState(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- #pragma unused ( refIn )
-
- Boolean setState, currentState = (**gPrefs).on_off;
- OSErr err = noErr;
- DescType theDescType;
- Size theSize;
- long result;
-
-
- // Get the state passed in.
- err = AEGetParamPtr(messagein, keyDirectObject, typeBoolean,
- &theDescType, (Ptr) &setState, sizeof(setState), &theSize);
-
-
- // Caller didn't send the boolean state parameter.
- if (err != noErr) {
- AddToReply( reply, "\p No boolean state was sent!", (long) err);
- goto ErrExit;
- }
- else
- (**gPrefs).on_off = setState;
-
- // Is the speech manager available?
- err = Gestalt( gestaltSpeechAttr, &result);
- if ((err != noErr) || !(result & (1 << gestaltSpeechMgrPresent))) {
- AddToReply( reply, "\p The Text To Speech Manager is not installed!", (long) err);
- }
-
-
- ErrExit:
- // Always return the current state
- return(AEPutParamPtr(reply, keyDirectObject, typeBoolean,
- (Ptr) ¤tState, sizeof(currentState)));
- }
-
- #pragma segment MAIN
- pascal OSErr AESetBeepSayState(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- long hostA5;
- Handle ourA5 = *OldA5();
- OSErr err;
-
- hostA5 = GetA5();
-
-
- SetA5((long)StripAddress((*ourA5)) + A5Size() - 32);
-
- err = _AESetBeepSayState( messagein, reply, refIn);
-
- RestoreA5World( hostA5);
-
- return ( err);
-
- }
-
- pascal OSErr _AESpeakBeepSayPhrase(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- #pragma unused ( refIn )
-
- Str255 theText;
- OSErr err = noErr;
- DescType theDescType;
- Size theSize;
- long result;
- VoiceSpec undefinedVoice;
-
- (void) MakeVoiceSpec('????', '????', &undefinedVoice);
-
- if ( undefinedVoice == (**gPrefs).theVoice) {
- AddToReply( reply, "\pLil´ BeepSay must be configured using the control panel prior to use!",
- (long) abortErr);
- goto ErrExit;
- }
-
- // Get the character string to speak
- err = AEGetParamPtr(messagein, keyDirectObject, typeChar,
- &theDescType, (Ptr) &theText[1], sizeof(theText), &theSize);
-
-
- // Caller didn't send the bloody phrase.
- if (err != noErr) {
- AddToReply( reply, "\p No phrase was sent to speak!", (long) err);
- goto ErrExit;
- }
-
- // Is the speech manager available?
- err = Gestalt( gestaltSpeechAttr, &result);
- if ((err != noErr) || !(result & (1 << gestaltSpeechMgrPresent))) {
- AddToReply( reply, "\p The Text To Speech Manager is not installed!", (long) err);
- goto ErrExit;
- }
-
- theText[0] = (char) theSize;
- err = OurSpeakTheText(theText, !kDoAsync); // Complete the phrase.
- if ( err != noErr)
- AddToReply( reply, "\p Couldn't speak the phrase!", (long) err);
-
- ErrExit:
- return(err);
- }
-
- pascal OSErr AESpeakBeepSayPhrase(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- long hostA5;
- Handle ourA5 = *OldA5();
- OSErr err;
-
- hostA5 = GetA5();
-
-
- SetA5((long)StripAddress((*ourA5)) + A5Size() - 32);
-
- err = _AESpeakBeepSayPhrase( messagein, reply, refIn);
-
- RestoreA5World( hostA5);
-
- return ( err);
-
- }
-